3-2 情景二:开发体验提升,ts&js运行时升级
场景描述
上一节的 Webpack 升级场景相对简单,本节讨论更复杂的情况:Webpack 配置本身就使用了大量第三方插件,分成了 development 和 production 两种模式,且 production 模式下使用了 TerserPlugin 进行代码压缩。
在这种复杂的配置基础上,如何通过升级运行时来提升开发体验。
TS 运行时生态
在 Node.js 环境中直接运行 TypeScript 文件,有以下几种方案:
1. ts-node
最传统的 TypeScript 运行时,通过 Node.js 的 register hook 拦截 .ts 文件的加载并进行实时编译。
# 安装
npm install ts-node --save-dev
# 使用
npx ts-node src/index.ts
bash
优点:兼容性最好,支持所有 TypeScript 特性。 缺点:启动速度慢,大型项目的启动时间可能达到数秒。
2. tsx
基于 esbuild 的 TypeScript 运行时,编译速度极快。
# 安装
npm install tsx --save-dev
# 使用
npx tsx src/index.ts
bash
优点:启动速度快(比 ts-node 快 10 倍以上),支持 watch 模式。 缺点:部分高级 TypeScript 特性可能不完全支持。
3. esbuild-runner
另一个基于 esbuild 的方案:
npm install esbuild-runner --save-dev
npx esr src/index.ts
bash
4. SWC(@swc/node)
基于 Rust 编写的 TypeScript 编译器:
npm install @swc/core @swc/node --save-dev
npx swc-node src/index.ts
bash
运行时性能对比
| 运行时 | 编译引擎 | 启动速度 | 兼容性 | 适用场景 |
|---|---|---|---|---|
| ts-node | tsc(JS) | 慢 | 100% | 需要完整 TS 支持的项目 |
| tsx | esbuild(Go) | 快 | ~95% | 日常开发、脚本运行 |
| @swc/node | SWC(Rust) | 快 | ~95% | 已使用 SWC 的项目 |
| esbuild-runner | esbuild(Go) | 快 | ~95% | 轻量级脚本 |
开发模式下的 Webpack 配置优化
在 development 模式下,可以通过以下方式提升开发体验:
1. 使用 esbuild-loader 替代 ts-loader/babel-loader
const { EsbuildPlugin } = require('esbuild-loader');
module.exports = {
module: {
rules: [
{
test: /\.[jt]sx?$/,
loader: 'esbuild-loader',
options: {
target: 'es2015'
}
}
]
}
}
javascript
esbuild-loader 基于 Go 语言的 esbuild,编译速度比 babel-loader 快 100 倍以上。
2. 配置 Webpack 5 持久化缓存
module.exports = {
cache: {
type: 'filesystem',
buildDependencies: {
config: [__filename]
}
}
}
javascript
首次构建后,后续构建会利用磁盘缓存,速度大幅提升。
3. 优化 devtool 配置
// development 模式推荐
module.exports = {
devtool: 'eval-cheap-module-source-map'
}
javascript
eval-cheap-module-source-map 在构建速度和调试体验之间取得了较好的平衡。eval 模式利用 eval() 的 SourceURL 功能,重建速度极快。
Production 模式下的 TerserPlugin 配置
在 production 模式中,代码压缩(minification)是最耗时的步骤之一。TerserPlugin 是 Webpack 默认的 JavaScript 压缩工具:
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
optimization: {
minimizer: [
new TerserPlugin({
parallel: true, // 开启多线程
terserOptions: {
compress: {
drop_console: true, // 移除 console
drop_debugger: true // 移除 debugger
}
}
})
]
}
}
javascript
可以用 esbuild-loader 的 EsbuildPlugin 替代 TerserPlugin 以获得更快的压缩速度:
optimization: {
minimizer: [
new EsbuildPlugin({
target: 'es2015',
css: true // 同时压缩 CSS
})
]
}
javascript
运行时升级建议
| 项目类型 | 推荐运行时 | 理由 |
|---|---|---|
| 新项目开发 | tsx | 启动快,开发体验好 |
| 需要完整 TS 支持 | ts-node + swc 插件 | 兼顾速度和兼容性 |
| CI/CD 构建 | 直接用 tsc 编译 | 最稳定可靠 |
| Webpack 配置文件 | tsx | 快速加载 webpack.config.ts |
参考资源
↑